import { SceneType } from "@/store/sceneStore";
import type TiledMap from "tiled-types";

/**
 * 渲染单个图层
 */
export const renderLayer = (
  ctx: CanvasRenderingContext2D,
  layer: any,
  map: TiledMap,
  tileset: HTMLImageElement
) => {
  for (let y = 0; y < layer.height; y++) {
    for (let x = 0; x < layer.width; x++) {
      // 计算瓦片在瓦片集中的索引
      const index = y * layer.width + x;
      // 获取瓦片ID
      const tileId = layer.data[index];

      if (tileId === 0) continue;

      // 找到这个瓦片ID属于哪个瓦片集
      const tilesetIdx = findTileset(tileId, map);
      if (tilesetIdx === -1) continue;

      const currentTileset = map.tilesets[tilesetIdx];
      const localId = tileId - currentTileset.firstgid;

      // 计算瓦片在瓦片集图片中的位置
      const tilesPerRow = Math.floor(tileset.width / map.tilewidth);
      const sourceX = (localId % tilesPerRow) * map.tilewidth;
      const sourceY = Math.floor(localId / tilesPerRow) * map.tileheight;

      const scaledWidth = map.tilewidth;
      const scaledHeight = map.tileheight;

      ctx.drawImage(
        tileset, // 图像源
        sourceX, // 在源图像上的裁剪起始坐标(x,y)
        sourceY,
        map.tilewidth, // 裁剪的宽度和高度
        map.tileheight,
        x * scaledWidth, // 在画布上绘制的位置坐标(x,y)
        y * scaledHeight,
        scaledWidth, // 绘制到画布上的宽度和高度
        scaledHeight
      );
    }
  }
};

// 查找对应的 tileset
const findTileset = (tileId: number, map: TiledMap): number => {
  for (let i = map.tilesets.length - 1; i >= 0; i--) {
    if (tileId >= map.tilesets[i].firstgid) {
      return i;
    }
  }
  return -1;
};

/**
 * 处理农场场景的图层
 * @param ctx 画布上下文
 * @param layers 图层数组
 * @param map Tiled地图数据
 * @param tileset 瓦片集图像
 * @param renderUpperLayers 是否渲染上层图层
 */
export const processFarmLayers = (
  ctx: CanvasRenderingContext2D,
  layer: any,
  map: TiledMap,
  tileset: Record<string, HTMLImageElement>,
  renderUpperLayers: boolean = false
) => {
  if (layer.type === "group") {
    if (
      layer.name === "building" &&
      layer.layers &&
      Array.isArray(layer.layers)
    ) {
      // 对于building组，根据renderUpperLayers决定渲染哪些子图层
      layer.layers.forEach((subLayer: any) => {
        if (subLayer.name === "building-up" && renderUpperLayers) {
          renderLayer(ctx, subLayer, map, tileset.house);
        } else if (subLayer.name !== "building-up" && !renderUpperLayers) {
          renderLayer(ctx, subLayer, map, tileset.house);
        }
      });
    } else if (layer.layers && Array.isArray(layer.layers)) {
      // 递归处理其他组图层
      processLayers(ctx, layer.layers, map, tileset, renderUpperLayers);
    }
  }
  // 处理普通图层
  else if (layer.type === "tilelayer") {
    if (
      (layer.name === "building-up" || layer.name.includes("upper")) &&
      renderUpperLayers
    ) {
      renderLayer(ctx, layer, map, tileset.house);
    } else if (
      layer.name !== "building-up" &&
      !layer.name.includes("upper") &&
      !renderUpperLayers
    ) {
      let tilesetToUse = tileset.default;
      if (layer.name === "building-down" || layer.name.includes("building")) {
        tilesetToUse = tileset.house;
      }
      renderLayer(ctx, layer, map, tilesetToUse);
    }
  }
};

/**
 * 处理房屋内部场景的图层
 * @param ctx 画布上下文
 * @param layers 图层数组
 * @param map Tiled地图数据
 * @param tileset 瓦片集图像
 * @param renderUpperLayers 是否渲染上层图层
 */
export const processHouseLayers = (
  ctx: CanvasRenderingContext2D,
  layer: any,
  map: TiledMap,
  tileset: Record<string, HTMLImageElement>,
  renderUpperLayers: boolean
) => {
  if (layer.type === "group" && layer.layers && Array.isArray(layer.layers)) {
    // 递归处理组图层
    processLayers(ctx, layer.layers, map, tileset, renderUpperLayers);
  } else if (layer.type === "tilelayer") {
    // 房屋内部简单处理，不区分上下层
    renderLayer(ctx, layer, map, tileset.farmhouse);
  }
};

/**
 * 处理图层
 * @param ctx 画布上下文
 * @param layers 图层数组
 * @param map Tiled地图数据
 * @param tileset 瓦片集图像
 * @param renderUpperLayers 是否渲染上层图层
 * @param sceneType 场景类型
 */
export const processLayers = (
  ctx: CanvasRenderingContext2D,
  layers: any[],
  map: TiledMap,
  tileset: Record<string, HTMLImageElement>,
  renderUpperLayers: boolean = false,
  sceneType: SceneType = SceneType.FARM
) => {
  layers.forEach((layer) => {
    if (sceneType === SceneType.FARM) {
      processFarmLayers(ctx, layer, map, tileset, renderUpperLayers);
    } else if (sceneType === SceneType.HOUSE) {
      processHouseLayers(ctx, layer, map, tileset, renderUpperLayers);
    } else {
      if (
        layer.type === "group" &&
        layer.layers &&
        Array.isArray(layer.layers)
      ) {
        processLayers(
          ctx,
          layer.layers,
          map,
          tileset,
          renderUpperLayers,
          sceneType
        );
      } else if (layer.type === "tilelayer") {
        renderLayer(ctx, layer, map, tileset.default);
      }
    }
  });
};
